package com.weixue.service.impl;

import com.weixue.common.*;
import com.weixue.controller.vo.*;
import com.weixue.dao.NongFuMallGoodsMapper;
import com.weixue.dao.NongFuMallOrderItemMapper;
import com.weixue.dao.NongFuMallOrderMapper;
import com.weixue.dao.NongFuMallShoppingCartItemMapper;
import com.weixue.entity.NongFuMallGoods;
import com.weixue.entity.NongFuMallOrder;
import com.weixue.entity.NongFuMallOrderItem;
import com.weixue.entity.StockNumDTO;
import com.weixue.service.NongFuMallOrderService;
import com.weixue.utils.BeanUtil;
import com.weixue.utils.NumberUtil;
import com.weixue.utils.PageQueryUtil;
import com.weixue.utils.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

@Service
public class NongFuMallOrderServiceImpl implements NongFuMallOrderService {

    @Autowired
    private NongFuMallOrderMapper nongFuMallOrderMapper;
    @Autowired
    private NongFuMallOrderItemMapper nongFuMallOrderItemMapper;
    @Autowired
    private NongFuMallShoppingCartItemMapper nongFuMallShoppingCartItemMapper;
    @Autowired
    private NongFuMallGoodsMapper nongFuMallGoodsMapper;

    @Override
    public PageResult getNongFuMallOrdersPage(PageQueryUtil pageUtil) {
        List<NongFuMallOrder> nongFuMallOrders = nongFuMallOrderMapper.findNongFuMallOrderList(pageUtil);
        int total = nongFuMallOrderMapper.getTotalNongFuMallOrders(pageUtil);
        PageResult pageResult = new PageResult(nongFuMallOrders, total, pageUtil.getLimit(), pageUtil.getPage());
        return pageResult;
    }

    @Override
    @Transactional
    public String updateOrderInfo(NongFuMallOrder nongFuMallOrder) {
        NongFuMallOrder temp = nongFuMallOrderMapper.selectByPrimaryKey(nongFuMallOrder.getOrderId());
        //不为空且orderStatus>=0且状态为出库之前可以修改部分信息
        if (temp != null && temp.getOrderStatus() >= 0 && temp.getOrderStatus() < 3) {
            temp.setTotalPrice(nongFuMallOrder.getTotalPrice());
            temp.setUserAddress(nongFuMallOrder.getUserAddress());
            temp.setUpdateTime(new Date());
            if (nongFuMallOrderMapper.updateByPrimaryKeySelective(temp) > 0) {
                return ServiceResultEnum.SUCCESS.getResult();
            }
            return ServiceResultEnum.DB_ERROR.getResult();
        }
        return ServiceResultEnum.DATA_NOT_EXIST.getResult();
    }

    @Override
    @Transactional
    public String checkDone(Long[] ids) {
        //查询所有的订单 判断状态 修改状态和更新时间
        List<NongFuMallOrder> orders = nongFuMallOrderMapper.selectByPrimaryKeys(Arrays.asList(ids));
        String errorOrderNos = "";
        if (!CollectionUtils.isEmpty(orders)) {
            for (NongFuMallOrder nongFuMallOrder : orders) {
                if (nongFuMallOrder.getIsDeleted() == 1) {
                    errorOrderNos += nongFuMallOrder.getOrderNo() + " ";
                    continue;
                }
                if (nongFuMallOrder.getOrderStatus() != 1) {
                    errorOrderNos += nongFuMallOrder.getOrderNo() + " ";
                }
            }
            if (StringUtils.isEmpty(errorOrderNos)) {
                //订单状态正常 可以执行配货完成操作 修改订单状态和更新时间
                if (nongFuMallOrderMapper.checkDone(Arrays.asList(ids)) > 0) {
                    return ServiceResultEnum.SUCCESS.getResult();
                } else {
                    return ServiceResultEnum.DB_ERROR.getResult();
                }
            } else {
                //订单此时不可执行出库操作
                if (errorOrderNos.length() > 0 && errorOrderNos.length() < 100) {
                    return errorOrderNos + "订单的状态不是支付成功无法执行出库操作";
                } else {
                    return "你选择了太多状态不是支付成功的订单，无法执行配货完成操作";
                }
            }
        }
        //未查询到数据 返回错误提示
        return ServiceResultEnum.DATA_NOT_EXIST.getResult();
    }

    @Override
    @Transactional
    public String checkOut(Long[] ids) {
        //查询所有的订单 判断状态 修改状态和更新时间
        List<NongFuMallOrder> orders = nongFuMallOrderMapper.selectByPrimaryKeys(Arrays.asList(ids));
        String errorOrderNos = "";
        if (!CollectionUtils.isEmpty(orders)) {
            for (NongFuMallOrder nongFuMallOrder : orders) {
                if (nongFuMallOrder.getIsDeleted() == 1) {
                    errorOrderNos += nongFuMallOrder.getOrderNo() + " ";
                    continue;
                }
                if (nongFuMallOrder.getOrderStatus() != 1 && nongFuMallOrder.getOrderStatus() != 2) {
                    errorOrderNos += nongFuMallOrder.getOrderNo() + " ";
                }
            }
            if (StringUtils.isEmpty(errorOrderNos)) {
                //订单状态正常 可以执行出库操作 修改订单状态和更新时间
                if (nongFuMallOrderMapper.checkOut(Arrays.asList(ids)) > 0) {
                    return ServiceResultEnum.SUCCESS.getResult();
                } else {
                    return ServiceResultEnum.DB_ERROR.getResult();
                }
            } else {
                //订单此时不可执行出库操作
                if (errorOrderNos.length() > 0 && errorOrderNos.length() < 100) {
                    return errorOrderNos + "订单的状态不是支付成功或配货完成无法执行出库操作";
                } else {
                    return "你选择了太多状态不是支付成功或配货完成的订单，无法执行出库操作";
                }
            }
        }
        //未查询到数据 返回错误提示
        return ServiceResultEnum.DATA_NOT_EXIST.getResult();
    }

    @Override
    @Transactional
    public String closeOrder(Long[] ids) {
        //查询所有的订单 判断状态 修改状态和更新时间
        List<NongFuMallOrder> orders = nongFuMallOrderMapper.selectByPrimaryKeys(Arrays.asList(ids));
        String errorOrderNos = "";
        if (!CollectionUtils.isEmpty(orders)) {
            for (NongFuMallOrder nongFuMallOrder : orders) {
                // isDeleted=1 一定为已关闭订单
                if (nongFuMallOrder.getIsDeleted() == 1) {
                    errorOrderNos += nongFuMallOrder.getOrderNo() + " ";
                    continue;
                }
                //已关闭或者已完成无法关闭订单
                if (nongFuMallOrder.getOrderStatus() == 4 || nongFuMallOrder.getOrderStatus() < 0) {
                    errorOrderNos += nongFuMallOrder.getOrderNo() + " ";
                }
            }
            if (StringUtils.isEmpty(errorOrderNos)) {
                //订单状态正常 可以执行关闭操作 修改订单状态和更新时间
                if (nongFuMallOrderMapper.closeOrder(Arrays.asList(ids), NongFuMallOrderStatusEnum.ORDER_CLOSED_BY_JUDGE.getOrderStatus()) > 0) {
                    return ServiceResultEnum.SUCCESS.getResult();
                } else {
                    return ServiceResultEnum.DB_ERROR.getResult();
                }
            } else {
                //订单此时不可执行关闭操作
                if (errorOrderNos.length() > 0 && errorOrderNos.length() < 100) {
                    return errorOrderNos + "订单不能执行关闭操作";
                } else {
                    return "你选择的订单不能执行关闭操作";
                }
            }
        }
        //未查询到数据 返回错误提示
        return ServiceResultEnum.DATA_NOT_EXIST.getResult();
    }

    /**
     * Day37
     *      订单生成
     *      就是先验证，再进行订单数据封装，最后将订单数据和订单项数据保存到数据库中。
     *          ①检查在结算商品中是否包含已下架商品，如果有则抛出一个异常，无下架商品则继续后续流程
     *          ②判断商品数据和商品库存，如果商品数据有误或者商品库存不足则抛出异常，一切正常则继续走后续流程
     *          ③对象的非空判断
     *          ④在生成订单后，购物项数据需要删除，这里调用NewBeeMallShoppingCartItemMapper.deleteBatch()方法将这些数据批量删除
     *          ⑤更新商品库存记录
     *          ⑥判断订单价格，如果所有购物项加起来的数据为0或者小于0则不继续生成订单
     *          ⑦生成订单号并封装NewBeeMallOrder对象，保存订单记录到数据库中
     *          ⑧封装订单项数据并保存订单项数据到数据库中
     *          ⑨返回新订单的订单号字段值
     *      因为订单确认设计多个表的修改，如果某个表修改出问题需要回滚一下
     */
    @Override
    @Transactional
    public String saveOrder(NongFuMallUserVO user, List<NongFuMallShoppingCartItemVO> myShoppingCartItems) {
        List<Long> itemIdList = myShoppingCartItems.stream().map(NongFuMallShoppingCartItemVO::getCartItemId).collect(Collectors.toList());
        List<Long> goodsIds = myShoppingCartItems.stream().map(NongFuMallShoppingCartItemVO::getGoodsId).collect(Collectors.toList());
        List<NongFuMallGoods> nongFuMallGoods = nongFuMallGoodsMapper.selectByPrimaryKeys(goodsIds);
        //检查是否包含已下架商品
        List<NongFuMallGoods> goodsListNotSelling = nongFuMallGoods.stream()
                .filter(nongFuMallGoodsTemp -> nongFuMallGoodsTemp.getGoodsSellStatus() != Constants.SELL_STATUS_UP)
                .collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(goodsListNotSelling)) {
            //goodsListNotSelling 对象非空则表示有下架商品
            NongFuMallException.fail(goodsListNotSelling.get(0).getGoodsName() + "已下架，无法生成订单");
        }
        Map<Long, NongFuMallGoods> nongFuMallGoodsMap = nongFuMallGoods.stream().collect(Collectors.toMap(NongFuMallGoods::getGoodsId, Function.identity(), (entity1, entity2) -> entity1));
        //判断商品库存
        for (NongFuMallShoppingCartItemVO shoppingCartItemVO : myShoppingCartItems) {
            //查出的商品中不存在购物车中的这条关联商品数据，直接返回错误提醒
            if (!nongFuMallGoodsMap.containsKey(shoppingCartItemVO.getGoodsId())) {
                NongFuMallException.fail(ServiceResultEnum.SHOPPING_ITEM_ERROR.getResult());
            }
            //存在数量大于库存的情况，直接返回错误提醒
            if (shoppingCartItemVO.getGoodsCount() > nongFuMallGoodsMap.get(shoppingCartItemVO.getGoodsId()).getStockNum()) {
                NongFuMallException.fail(ServiceResultEnum.SHOPPING_ITEM_COUNT_ERROR.getResult());
            }
        }
        //删除购物项
        if (!CollectionUtils.isEmpty(itemIdList) && !CollectionUtils.isEmpty(goodsIds) && !CollectionUtils.isEmpty(nongFuMallGoods)) {
            if (nongFuMallShoppingCartItemMapper.deleteBatch(itemIdList) > 0) {
                List<StockNumDTO> stockNumDTOS = BeanUtil.copyList(myShoppingCartItems, StockNumDTO.class);
                int updateStockNumResult = nongFuMallGoodsMapper.updateStockNum(stockNumDTOS);
                if (updateStockNumResult < 1) {
                    NongFuMallException.fail(ServiceResultEnum.SHOPPING_ITEM_COUNT_ERROR.getResult());
                }
                //生成订单号
                String orderNo = NumberUtil.genOrderNo();
                int priceTotal = 0;
                //保存订单
                NongFuMallOrder nongFuMallOrder = new NongFuMallOrder();
                nongFuMallOrder.setOrderNo(orderNo);
                nongFuMallOrder.setUserId(user.getUserId());
                nongFuMallOrder.setUserAddress(user.getAddress());
                //总价
                for (NongFuMallShoppingCartItemVO nongFuMallShoppingCartItemVO : myShoppingCartItems) {
                    priceTotal += nongFuMallShoppingCartItemVO.getGoodsCount() * nongFuMallShoppingCartItemVO.getSellingPrice();
                }
                if (priceTotal < 1) {
                    NongFuMallException.fail(ServiceResultEnum.ORDER_PRICE_ERROR.getResult());
                }
                nongFuMallOrder.setTotalPrice(priceTotal);
                //todo 订单body字段，用来作为生成支付单描述信息，暂时未接入第三方支付接口，故该字段暂时设为空字符串
                String extraInfo = "";
                nongFuMallOrder.setExtraInfo(extraInfo);
                //生成订单项并保存订单项纪录
                if (nongFuMallOrderMapper.insertSelective(nongFuMallOrder) > 0) {
                    //生成所有的订单项快照，并保存至数据库
                    List<NongFuMallOrderItem> nongFuMallOrderItems = new ArrayList<>();
                    for (NongFuMallShoppingCartItemVO nongFuMallShoppingCartItemVO : myShoppingCartItems) {
                        NongFuMallOrderItem nongFuMallOrderItem = new NongFuMallOrderItem();
                        //使用BeanUtil工具类将nongFuMallShoppingCartItemVO中的属性复制到nongFuMallOrderItem对象中
                        BeanUtil.copyProperties(nongFuMallShoppingCartItemVO, nongFuMallOrderItem);
                        //NongFuMallOrderMapper文件insert()方法中使用了useGeneratedKeys因此orderId可以获取到
                        nongFuMallOrderItem.setOrderId(nongFuMallOrder.getOrderId());
                        nongFuMallOrderItems.add(nongFuMallOrderItem);
                    }
                    //保存至数据库
                    if (nongFuMallOrderItemMapper.insertBatch(nongFuMallOrderItems) > 0) {
                        //所有操作成功后，将订单号返回，以供Controller方法跳转到订单详情
                        return orderNo;
                    }
                    NongFuMallException.fail(ServiceResultEnum.ORDER_PRICE_ERROR.getResult());
                }
                NongFuMallException.fail(ServiceResultEnum.DB_ERROR.getResult());
            }
            NongFuMallException.fail(ServiceResultEnum.DB_ERROR.getResult());
        }
        NongFuMallException.fail(ServiceResultEnum.SHOPPING_ITEM_ERROR.getResult());
        return ServiceResultEnum.SHOPPING_ITEM_ERROR.getResult();
    }

    @Override
    public NongFuMallOrderDetailVO getOrderDetailByOrderNo(String orderNo, Long userId) {
        NongFuMallOrder nongFuMallOrder = nongFuMallOrderMapper.selectByOrderNo(orderNo);
        if (nongFuMallOrder != null) {
            //todo 验证是否是当前userId下的订单，否则报错
            List<NongFuMallOrderItem> orderItems = nongFuMallOrderItemMapper.selectByOrderId(nongFuMallOrder.getOrderId());
            //获取订单项数据
            if (!CollectionUtils.isEmpty(orderItems)) {
                List<NongFuMallOrderItemVO> nongFuMallOrderItemVOS = BeanUtil.copyList(orderItems, NongFuMallOrderItemVO.class);
                NongFuMallOrderDetailVO nongFuMallOrderDetailVO = new NongFuMallOrderDetailVO();
                BeanUtil.copyProperties(nongFuMallOrder, nongFuMallOrderDetailVO);
                nongFuMallOrderDetailVO.setOrderStatusString(NongFuMallOrderStatusEnum.getNongFuMallOrderStatusEnumByStatus(nongFuMallOrderDetailVO.getOrderStatus()).getName());
                nongFuMallOrderDetailVO.setPayTypeString(PayTypeEnum.getPayTypeEnumByType(nongFuMallOrderDetailVO.getPayType()).getName());
                nongFuMallOrderDetailVO.setNongFuMallOrderItemVOS(nongFuMallOrderItemVOS);
                return nongFuMallOrderDetailVO;
            }
        }
        return null;
    }

    @Override
    public NongFuMallOrder getNongFuMallOrderByOrderNo(String orderNo) {
        return nongFuMallOrderMapper.selectByOrderNo(orderNo);
    }

    /**
     * Day38
     *      订单列表的数据获取
     */
    @Override
    public PageResult getMyOrders(PageQueryUtil pageUtil) {
        int total = nongFuMallOrderMapper.getTotalNongFuMallOrders(pageUtil);
        List<NongFuMallOrder> nongFuMallOrders = nongFuMallOrderMapper.findNongFuMallOrderList(pageUtil);
        List<NongFuMallOrderListVO> orderListVOS = new ArrayList<>();
        if (total > 0) {
            //数据转换 将实体类转成vo
            orderListVOS = BeanUtil.copyList(nongFuMallOrders, NongFuMallOrderListVO.class);
            //设置订单状态中文显示值
            for (NongFuMallOrderListVO nongFuMallOrderListVO : orderListVOS) {
                nongFuMallOrderListVO.setOrderStatusString(NongFuMallOrderStatusEnum.getNongFuMallOrderStatusEnumByStatus(nongFuMallOrderListVO.getOrderStatus()).getName());
            }
            List<Long> orderIds = nongFuMallOrders.stream().map(NongFuMallOrder::getOrderId).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(orderIds)) {
                List<NongFuMallOrderItem> orderItems = nongFuMallOrderItemMapper.selectByOrderIds(orderIds);
                Map<Long, List<NongFuMallOrderItem>> itemByOrderIdMap = orderItems.stream().collect(groupingBy(NongFuMallOrderItem::getOrderId));
                for (NongFuMallOrderListVO nongFuMallOrderListVO : orderListVOS) {
                    //封装每个订单列表对象的订单项数据
                    if (itemByOrderIdMap.containsKey(nongFuMallOrderListVO.getOrderId())) {
                        List<NongFuMallOrderItem> orderItemListTemp = itemByOrderIdMap.get(nongFuMallOrderListVO.getOrderId());
                        //将NongFuMallOrderItem对象列表转换成NongFuMallOrderItemVO对象列表
                        List<NongFuMallOrderItemVO> nongFuMallOrderItemVOS = BeanUtil.copyList(orderItemListTemp, NongFuMallOrderItemVO.class);
                        nongFuMallOrderListVO.setNongFuMallOrderItemVOS(nongFuMallOrderItemVOS);
                    }
                }
            }
        }
        PageResult pageResult = new PageResult(orderListVOS, total, pageUtil.getLimit(), pageUtil.getPage());
        return pageResult;
    }

    @Override
    public String cancelOrder(String orderNo, Long userId) {
        NongFuMallOrder nongFuMallOrder = nongFuMallOrderMapper.selectByOrderNo(orderNo);
        if (nongFuMallOrder != null) {
            //todo 验证是否是当前userId下的订单，否则报错
            //todo 订单状态判断
            if (nongFuMallOrderMapper.closeOrder(Collections.singletonList(nongFuMallOrder.getOrderId()), NongFuMallOrderStatusEnum.ORDER_CLOSED_BY_MALLUSER.getOrderStatus()) > 0) {
                return ServiceResultEnum.SUCCESS.getResult();
            } else {
                return ServiceResultEnum.DB_ERROR.getResult();
            }
        }
        return ServiceResultEnum.ORDER_NOT_EXIST_ERROR.getResult();
    }

    @Override
    public String finishOrder(String orderNo, Long userId) {
        NongFuMallOrder nongFuMallOrder = nongFuMallOrderMapper.selectByOrderNo(orderNo);
        if (nongFuMallOrder != null) {
            //todo 验证是否是当前userId下的订单，否则报错
            //todo 订单状态判断
            nongFuMallOrder.setOrderStatus((byte) NongFuMallOrderStatusEnum.ORDER_SUCCESS.getOrderStatus());
            nongFuMallOrder.setUpdateTime(new Date());
            if (nongFuMallOrderMapper.updateByPrimaryKeySelective(nongFuMallOrder) > 0) {
                return ServiceResultEnum.SUCCESS.getResult();
            } else {
                return ServiceResultEnum.DB_ERROR.getResult();
            }
        }
        return ServiceResultEnum.ORDER_NOT_EXIST_ERROR.getResult();
    }

    @Override
    public String paySuccess(String orderNo, int payType) {
        NongFuMallOrder nongFuMallOrder = nongFuMallOrderMapper.selectByOrderNo(orderNo);
        if (nongFuMallOrder != null) {
            //todo 订单状态判断 非待支付状态下不进行修改操作
            nongFuMallOrder.setOrderStatus((byte) NongFuMallOrderStatusEnum.OREDER_PAID.getOrderStatus());
            nongFuMallOrder.setPayType((byte) payType);
            nongFuMallOrder.setPayStatus((byte) PayStatusEnum.PAY_SUCCESS.getPayStatus());
            nongFuMallOrder.setPayTime(new Date());
            nongFuMallOrder.setUpdateTime(new Date());
            if (nongFuMallOrderMapper.updateByPrimaryKeySelective(nongFuMallOrder) > 0) {
                return ServiceResultEnum.SUCCESS.getResult();
            } else {
                return ServiceResultEnum.DB_ERROR.getResult();
            }
        }
        return ServiceResultEnum.ORDER_NOT_EXIST_ERROR.getResult();
    }

    @Override
    public List<NongFuMallOrderItemVO> getOrderItems(Long id) {
        NongFuMallOrder nongFuMallOrder = nongFuMallOrderMapper.selectByPrimaryKey(id);
        if (nongFuMallOrder != null) {
            List<NongFuMallOrderItem> orderItems = nongFuMallOrderItemMapper.selectByOrderId(nongFuMallOrder.getOrderId());
            //获取订单项数据
            if (!CollectionUtils.isEmpty(orderItems)) {
                List<NongFuMallOrderItemVO> nongFuMallOrderItemVOS = BeanUtil.copyList(orderItems, NongFuMallOrderItemVO.class);
                return nongFuMallOrderItemVOS;
            }
        }
        return null;
    }
}